﻿/*
 * The MIT License
 * 
 * Copyright 2008 Jeppe Burchardt and Pimm Hogeling
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

package org.dr.actionconsole.view
{
	import flash.display.CapsStyle;
	import flash.display.DisplayObject;
	import flash.display.LineScaleMode;
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.AntiAliasType;
	import flash.text.TextField
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.ui.Keyboard;
	import org.dr.actionconsole.data.CommandData;
	
	public class BasicConsoleView extends Sprite implements IConsoleView
	{
		private var _mode : Boolean = false;
		private var input : TextField;
		private var output : TextField;
		private var query:String;
		private var scrollbar : Sprite;
		
		/**
		* This is the basic ConsoleView class. If you want to use your own ConsoleView class you can alter this one or write one
		*  from scratch.
		*/
		public function BasicConsoleView() : void
		{
			input = new TextField();
			input.defaultTextFormat = new TextFormat("_sans", 9, 0xFFFFFF);
			input.antiAliasType = AntiAliasType.ADVANCED;
			input.type = TextFieldType.INPUT;
			addChild(input);
			
			output = new TextField();
			output.defaultTextFormat = new TextFormat("_sans", 9, 0xFFFFFF);
			output.antiAliasType = AntiAliasType.ADVANCED;
			output.wordWrap = true;
			output.useRichTextClipboard = true;
			addChild(output);
			
			scrollbar = new Sprite();
			scrollbar.buttonMode = true;
			addChild(scrollbar);
			
			addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
		/**
		 * Clears the console field.
		 */
		public function clearConsole() : void
		{
			output.text = "";
		}
		/**
		 * Returns the DisplayObject object that the console will add to the stage and try to keep on top of others.
		 */
		public function getDisplayObject() : DisplayObject
		{
			return this;
		}
		/**
		 * Returns what the user has inputted into he console. This method will be called when the enter key is pressed.
		 */
		public function getInput() : String
		{
			return input.text;
		}
		/**
		 * Sets the input of the console. This method will be called after the getInput method or when a user uses the history.
		 */
		public function setInput(value:String) : void
		{
			input.text = value;
			input.setSelection(value.length, value.length);
		}
		/**
		 * Opens or closes the console. True for open, false for close.
		 */
		public function setOpened(value:Boolean) : void
		{
			visible = value;
			if (value)
			{
				if (stage)
				{
					stage.focus = input;
				}
			}
		}
		/**
		 * Writes some text to the console.
		 */
		public function write(text:String, color:uint, font:String) : void
		{
			const start : uint = output.length;
			output.appendText(text);
			const end : uint = output.length;
			
			var delta : TextFormat = output.defaultTextFormat;
			delta.color = color;
			delta.font = font;
			
			output.setTextFormat(delta, start, end);
			output.scrollV = output.maxScrollV;
		}
		private function addedToStage(e:Event) : void
		{
			paint();
			
			stage.focus = input;
			scrollbar.addEventListener(MouseEvent.MOUSE_DOWN, startScroll);
			scrollbar.addEventListener(MouseEvent.MOUSE_UP, stopScroll);
			output.addEventListener(Event.SCROLL, updateScrollbar);
			stage.addEventListener(Event.RESIZE, paint);
		}
		private function paint(event:Event=null) : void
		{
			input.x = 3;
			input.y = stage.stageHeight - 16;
			input.height = 16;
			input.width = stage.stageWidth - 6;
			
			output.x = output.y = 3;
			output.width = stage.stageWidth - 6;
			output.height = stage.stageHeight - 16;
			
			graphics.clear();
			graphics.beginFill(0x000000, 0.7);
			graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight - 16);
			graphics.endFill();
			
			graphics.beginFill(0x333333, 0.7);
			graphics.drawRect(0, stage.stageHeight - 16, stage.stageWidth, 16);
			graphics.endFill();
			
			scrollbar.x = stage.stageWidth - 2;
			
			updateScrollbar();
		}
		private function scroll(event:Event=null) : void
		{
			output.scrollV = (scrollbar.mouseY / (scrollbar.height - 10)) * output.maxScrollV;
		}
		private function startScroll(e:Event):void
		{
			scroll();
			stage.addEventListener(MouseEvent.MOUSE_MOVE, scroll);
			stage.addEventListener(MouseEvent.MOUSE_UP, stopScroll);
		}
		private function stopScroll(e:Event):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, scroll);
			stage.removeEventListener(MouseEvent.MOUSE_UP, stopScroll);
		}
		private function updateScrollbar(event:Event=null) : void
		{
			const scrollbarHeight : int = stage.stageHeight - 17;
			const scrollbarSliderHeight : Number = (scrollbarHeight / output.textHeight) * scrollbarHeight;
			
			const scrollbarSliderY : Number = (scrollbarHeight - scrollbarSliderHeight) * (output.scrollV - 1) / (output.maxScrollV - 1);
			
			scrollbar.graphics.clear();
			scrollbar.graphics.lineStyle(5, 0x000000, 0.5, true, LineScaleMode.NORMAL, CapsStyle.SQUARE);
			scrollbar.graphics.moveTo(0, 2);
			scrollbar.graphics.lineTo(0, stage.stageHeight - 19);
			
			scrollbar.graphics.lineStyle(3, 0xFFFFFF, 0.5, true, LineScaleMode.NORMAL, CapsStyle.SQUARE);
			scrollbar.graphics.moveTo(0, scrollbarSliderY + 2);
			scrollbar.graphics.lineTo(0, scrollbarSliderY + scrollbarSliderHeight - 2);
			
			scrollbar.visible = (scrollbarSliderHeight < scrollbarHeight);
		}
	}
}